#include <set>

#include "Triangle.h"
#include "PArray.h"
#include "Tetrahedron.h"
#include "Node.h"

/*
Find all tets containing NOD, starting from START. 
*/
LinkArray<Tetrahedron> FindCell (Tetrahedron *start, Node * nod) 
{
	std::set<Tetrahedron*> done;
	LinkArray<Tetrahedron> todo;

	todo.Push (start);
	while (todo.Size ())
	{
		Tetrahedron * tet  = todo.Pop();
		if (done.find (tet) != done.end ())
			continue;

		done.insert (tet);

		for (int j =0;  j<4; j++)
		{
			Triangle * tr = tet->GetTriangle( j)->Mate ();
			if (tr && tr->ContainsB (nod))
			{
				todo.Push (tr->Tetra ());
			}
		}
	}

	LinkArray<Tetrahedron> found;
	for (std::set<Tetrahedron*>::const_iterator ki(done.begin());
		ki != done.end (); ki ++)
	{
		found.Push ((*ki));
	}
	return found;
}

/*
All tets connected with TET, containing E. Since this is a 1-D
sequence, a more elegant alg. could be used.
*/
LinkArray<Tetrahedron> FindEdgeCell (Simplex e, Tetrahedron  *tet)
{
	Simplex emate = e.GetMate ();

	LinkArray<Tetrahedron> component;
	LinkArray<Tetrahedron> todo;

	todo.Push (tet);
	while (todo.Size ())
	{
		Tetrahedron * t = todo.Pop ();
		if (component.Findl (t))
			continue;

		component.Push (t);
		for (int j =0;  j<4; j++)
		{
			Triangle * tri = t->GetTriangle( j)->Mate ();
			if (tri &&
				(tri->GetSet ().SubsetB (e) || tri->GetSet ().SubsetB (emate)))
			{
				assert (tri->Valid ());
				todo.Push (tri->Tetra ());
			}
		}
	}
	return component;
}



LinkArray<Triangle> FindSurfaceCell (Node * nod, Tetrahedron* tet)
{
	std::set<Tetrahedron*> done;
	LinkArray<Tetrahedron> todo;
	LinkArray<Triangle> surf;

	todo.Push (tet);
	while (todo.Size ())
	{
		Tetrahedron * tet  = todo.Pop();

		assert (tet->Valid ());

		if (done.find (tet) != done.end ())
			continue;

		done.insert (tet);
		for (int j =0;  j<4; j++)
		{
			Triangle * tr = tet->GetTriangle( j);
			if (tr->ContainsB ((Node*)nod))
			{
				assert (tr->Valid ());
				if (tr->Mate ())
					todo.Push (tr->Mate ()->Tetra ());
				else
					surf.Push (tr);
			}
		}
	}

	return surf;
}
